// CreateCoder.h

#ifndef __CREATE_CODER_H
#define __CREATE_CODER_H

#include "Common/COM/ICoder.h"

#include <vector>

#ifdef EXTERNAL_CODECS

struct CCodecInfoEx
{
  CString		Name;
  //CMethodId	Id;
	UINT64		Id;
  UINT32		NumInStreams;
  UINT32		NumOutStreams;
  bool			EncoderIsAssigned;
  bool			DecoderIsAssigned;
  bool IsSimpleCodec() const { return NumOutStreams == 1 && NumInStreams == 1; }
  CCodecInfoEx(): EncoderIsAssigned(false), DecoderIsAssigned(false) {}
  CCodecInfoEx(const CCodecInfoEx & obj):
	  Name(obj.Name),
	  Id(obj.Id),
	  NumInStreams(obj.NumInStreams),
	  NumOutStreams(obj.NumOutStreams),
	  EncoderIsAssigned(obj.EncoderIsAssigned),
	  DecoderIsAssigned(obj.DecoderIsAssigned)
  {
  }
  CCodecInfoEx & operator=(const CCodecInfoEx & obj)
  {
	  Name = obj.Name;
	  Id = obj.Id;
	  NumInStreams = obj.NumInStreams;
	  NumOutStreams = obj.NumOutStreams;
	  EncoderIsAssigned = obj.EncoderIsAssigned;
	  DecoderIsAssigned = obj.DecoderIsAssigned;
	  return *this;
  }
};

HRESULT LoadExternalCodecs(ICompressCodecsInfo *codecsInfo, std::vector<CCodecInfoEx> &externalCodecs);

#define PUBLIC_ISetCompressCodecsInfo public ISetCompressCodecsInfo,
#define QUERY_ENTRY_ISetCompressCodecsInfo MY_QUERYINTERFACE_ENTRY(ISetCompressCodecsInfo)
#define DECL_ISetCompressCodecsInfo STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo);
#define IMPL_ISetCompressCodecsInfo2(x) \
STDMETHODIMP x::SetCompressCodecsInfo(ICompressCodecsInfo *compressCodecsInfo) { \
  COM_TRY_BEGIN _codecsInfo = compressCodecsInfo;  return LoadExternalCodecs(_codecsInfo, _externalCodecs); COM_TRY_END }
#define IMPL_ISetCompressCodecsInfo IMPL_ISetCompressCodecsInfo2(CHandler)

#define EXTERNAL_CODECS_VARS2 _codecsInfo, &_externalCodecs

#define DECL_EXTERNAL_CODECS_VARS CComPtr<ICompressCodecsInfo> _codecsInfo; std::vector<CCodecInfoEx> _externalCodecs;
#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2,

#define DECL_EXTERNAL_CODECS_LOC_VARS2 ICompressCodecsInfo *codecsInfo, const std::vector<CCodecInfoEx> *externalCodecs
#define EXTERNAL_CODECS_LOC_VARS2 codecsInfo, externalCodecs

#define DECL_EXTERNAL_CODECS_LOC_VARS DECL_EXTERNAL_CODECS_LOC_VARS2,
#define EXTERNAL_CODECS_LOC_VARS EXTERNAL_CODECS_LOC_VARS2,

#else

#define PUBLIC_ISetCompressCodecsInfo
#define QUERY_ENTRY_ISetCompressCodecsInfo
#define DECL_ISetCompressCodecsInfo
#define IMPL_ISetCompressCodecsInfo
#define EXTERNAL_CODECS_VARS2
#define DECL_EXTERNAL_CODECS_VARS
#define EXTERNAL_CODECS_VARS EXTERNAL_CODECS_VARS2
#define DECL_EXTERNAL_CODECS_LOC_VARS2
#define EXTERNAL_CODECS_LOC_VARS2
#define DECL_EXTERNAL_CODECS_LOC_VARS
#define EXTERNAL_CODECS_LOC_VARS

#endif

bool FindMethod(
  DECL_EXTERNAL_CODECS_LOC_VARS
  const CString &name, UINT64 &methodId, UINT32 &numInStreams, UINT32 &numOutStreams);

bool FindMethod(
  DECL_EXTERNAL_CODECS_LOC_VARS
  UINT64 methodId, CString &name);


HRESULT CreateCoder(
  DECL_EXTERNAL_CODECS_LOC_VARS
  UINT64 methodId,
  CComPtr<ICompressFilter> &filter,
  CComPtr<ICompressCoder> &coder,
  CComPtr<ICompressCoder2> &coder2,
  bool encode, bool onlyCoder);

HRESULT CreateCoder(
  DECL_EXTERNAL_CODECS_LOC_VARS
  UINT64 methodId,
  CComPtr<ICompressCoder> &coder,
  CComPtr<ICompressCoder2> &coder2,
  bool encode);

HRESULT CreateCoder(
  DECL_EXTERNAL_CODECS_LOC_VARS
  UINT64 methodId,
  CComPtr<ICompressCoder> &coder, bool encode);

HRESULT CreateFilter(
  DECL_EXTERNAL_CODECS_LOC_VARS
  UINT64 methodId,
  CComPtr<ICompressFilter> &filter,
  bool encode);

#endif
